<template>
  <view class="a-form" :class="{'filter-model':pageType=='filter','show-y-scroll-bar':pageType!=='filter'}">
    <view class="form-remark" v-if="remarkCfg&&remarkCfg.top" :style="[remarkCfg.top.style]">
      {{remarkCfg.top.content||''}}
    </view>
    <view class="grid" v-if="gridList&&gridList.length>0">
      <view class="w-full" v-for="(item,iIndex) in gridList">
        <view class="sub-title" v-if="item.subTitle">
          <text>{{item.subTitle}}</text>
          <view class="subsection" v-if="item.switchDisplay">
            <view class="subsection-item" :class="{active:item.display===true}" @click="changeGridDisplay(iIndex,true)">
              显示
            </view>
            <view class="subsection-item" :class="{active:item.display===false}"
              @click="changeGridDisplay(iIndex,false)">
              隐藏
            </view>
          </view>
        </view>
        <view class="grid-area" :style="item._style" v-show="item.display!==false">
          <view class="field-item" :style="field._area"
            :class="{'hidden':showField(field)!==true||field.display===false,'is-child-list':field&&['addchildlist','updatechildlist','detailchildlist','detail'].includes(field.use_type)}"
            v-for="(field,fIndex) in item.cols" :key="fIndex">
            <form-item :class="{'section-top':field.section,'before-section':eleIsBeforeSection(allField,fIndex)}"
              :srvApp="srvApp" :serviceNo="serviceNo" :form-type="formType" :procData="procData"
              :labelPosition="labelPosition" :fieldsModel="fieldModel" :mainData="mainData" :optionMode="optionMode"
              @on-value-change="onValChange" @on-value-blur="onValBlur" @chooseLocation="chooseLocation" :key="field.id"
              :field="field" :pageType="pageType" :ref="'fitem'+iIndex" :section-top="field.section?true:false"
              :before-section="eleIsBeforeSection(allField,fIndex)" @setColData="setColData"
              @setFieldModel="setFieldModel" @date-change="dateChange" @date-time-change="dateTimeChange"
              @on-childlist-change="childListChange($event,field)" @on-right-button="onRightButton">
            </form-item>
          </view>
        </view>
      </view>
    </view>
    <template class="form-box" v-else>
      <view class="field-item"
        :class="{'hidden':showField(field)!==true||!field.display,'is-child-list':field&&['addchildlist','updatechildlist','detailchildlist','detail'].includes(field.use_type)}"
        v-for="(field,fIndex) in allField" :key="fIndex">
        <view class="section-name" :class="{'show':showSectionName}" v-if="field.section">
          <text v-if="showSectionName">{{field.section}}</text>
        </view>
        <form-item :class="{'section-top':field.section,'before-section':eleIsBeforeSection(allField,fIndex)}"
          :srvApp="srvApp" :serviceNo="serviceNo" :form-type="formType" :procData="procData"
          :labelPosition="labelPosition" :fieldsModel="fieldModel" :mainData="mainData" :optionMode="optionMode"
          @on-value-change="onValChange" @on-value-blur="onValBlur" @chooseLocation="chooseLocation" :key="field.id"
          :field="field" :pageType="pageType" ref="fitem" :section-top="field.section?true:false"
          :before-section="eleIsBeforeSection(allField,fIndex)" @setColData="setColData" @setFieldModel="setFieldModel"
          @date-change="dateChange" @on-childlist-change="childListChange($event,field)"
          @date-time-change="dateTimeChange" @on-right-button="onRightButton">
        </form-item>
      </view>
    </template>
    <view class="form-remark" v-if="remarkCfg&&remarkCfg.bottom" :style="[remarkCfg.bottom.style]">
      {{remarkCfg.bottom.content||''}}
    </view>
  </view>
</template>

<script>
  import formItem from '../a-form-item/a-form-item.vue'
  // import ChildList from '@/pages/public/components/child-list/child-list.vue'
  export default {
    name: 'aForm',
    components: {
      // ChildList
      formItem
    },
    props: {
      mainData: {
        type: [Object, Boolean]
      },
      fields: {
        type: Array,
        required: true
      },
      formType: {
        type: String,
        default: 'add' //add||update
      },
      pageType: {
        type: String,
        default: 'form'
      },
      procData: {
        type: Object,
        default () {
          return {};
        }
      },
      labelPosition: {
        type: String,
        default: 'left' //left|top
      },
      optionMode: {
        type: String,
        default: 'normal' //选项的样式 normal | button
      },
      srvApp: {
        type: String
      },
      moreConfig: {
        type: Object,
        default () {
          return {};
        }
      },
      gridCfg: {
        type: [Array, Object],
        default: () => {
          return []
        }
      }
    },

    async created() {
      const oldFieldModel = this.oldField.reduce((res, cur) => {

        if (cur.value) {
          if (cur.column) {
            res[cur.column] = cur.value
          } else if (cur.columns) {
            res[cur.columns] = cur.value
          }
        } else if (cur.defaultValue) {
          if (cur.column) {
            res[cur.column] = cur.value
          } else if (cur.columns) {
            res[cur.columns] = cur.value
          }
        }
        if (cur.columns === 'service_people_no' && res[cur.columns]) {
          this.serviceNo = res[cur.columns]
        }
        return res
      }, {})
      this.oldFieldModel = this.deepClone(oldFieldModel)
      this.fieldModel = this.deepClone(oldFieldModel)
      this.setGridList()
    },
    computed: {
      fieldsMap() {
        if (Array.isArray(this.fields)) {
          return this.fields.reduce((pre, cur) => {
            if (cur.constraint_name || cur?.foreign_key?.constraint_name) {
              pre[cur.constraint_name || cur?.foreign_key?.constraint_name] = cur
            } else {
              pre[cur.column] = cur;
            }
            return pre
          }, {})
        }
        return {}
      },

      showSectionName() {
        return this.moreConfig?.showSectionName
      },
      remarkCfg() {
        if (this.moreConfig?.remark_cfg) {
          return this.moreConfig?.remark_cfg
        }
      },
    },
    data() {
      return {
        serviceNo: '',
        allField: [],
        oldField: [],
        fieldModel: {},
        oldFieldModel: {},
        more_config: {
          col_relation: []
        },
        gridList: [],
        childListData: {}
      };
    },
    methods: {
      onRightButton(btn, data, uuid) {
        this.$emit("on-right-button", btn, data, uuid);
      },
      childListChange(e, field) {
        // if (field && this.showField(field) !== true) {
        //   return
        // }
        console.log(e);
        if (e?.key && e.list) {
          this.childListData[e.key] = e.list
        }
      },
      changeGridDisplay(index, display) {
        this.$set(this.gridList[index], 'display', display)
      },
      setGridList() {
        if (Array.isArray(this.gridCfg) && this.gridCfg.length > 0) {
          let gridCfg = this.deepClone(this.gridCfg)
          const res = gridCfg.map(item => {
            if (item.range && item.range.split(',').length == 2) {
              let range = item.range.split(',')
              // grid-template-rows
              item.gtr = `repeat(${range[1]}, 1fr)`;
              // grid-template-columns
              item.gtc = `repeat(${range[1]}, 1fr)`;
              item._style = `grid-template-columns: repeat(${range[1]}, 1fr);
    grid-template-rows: repeat(${range[0]}, 1fr);
    grid-column-gap: ${item.columnGap};
    grid-row-gap:${item.rowGap};background-color:${item.bg};`
              if (Array.isArray(item.cols)) {
                item.cols = item.cols.map(col => {
                  let _area = ''
                  if (col.area) {
                    _area = `grid-area:${col.area.replace(/\,/g, '/')};`
                  }
                  if (col['grid-column-start']) {
                    _area += `grid-column-start:${col['grid-column-start']};`
                  }
                  if (col['grid-row-start']) {
                    _area += `grid-row-start:${col['grid-row-start']};`
                  }
                  let resCol = {
                    _area,
                    ...col,
                    ...this.fieldsMap[col.col] || {}
                  }
                  if (col.limit) {
                    resCol.limit = col.limit
                  }
                  if (col.label === false) {
                    resCol.hideLabel = true
                  }
                  return resCol
                })
              }
            }
            return item
          })
          this.gridList = res
        }
      },
      dateChange(range) {
        const {
          start_col,
          end_col
        } = range?.moreConfig || {}
        if (start_col && end_col) {
          this.allField = this.allField.map(item => {
            if (item.column === start_col) {
              item.value = range.colData['start']
              this.fieldModel[start_col] = range.colData['start']
            }
            if (item.column === end_col) {
              item.value = range.colData['end']
              this.fieldModel[end_col] = range.colData['end']
            }
            return item
          })
        }
      },
      dateTimeChange(e) {
        const start_time_col = e?.moreConfig?.start_time_col
        const end_time_col = e?.moreConfig?.end_time_col
        if (start_time_col && end_time_col) {
          this.allField = this.allField.map(item => {
            if (item.column === start_time_col) {
              item.value = e.colData['time_start']
              this.fieldModel[start_time_col] = e.colData['time_start']
            }
            if (item.column === end_time_col) {
              item.value = e.colData['time_end']
              this.fieldModel[end_time_col] = e.colData['time_end']
            }
            return item
          })
        }

      },
      eleIsBeforeSection(allField, index) {
        let item = allField[index]
        if (index + 1 < allField.length) {
          let nextItem = allField[index + 1]
          if (nextItem?.section) {
            return true
          }
        }
        if (index === allField.length - 1) {
          return true
        }
      },
      showField(field) {
        const mainData = this.mainData || {}
        if (['addchildlist', 'updatechildlist', 'detail', 'detailchildlist'].includes(field.use_type)) {
          // return true
          if (field?.foreign_key?.show_child_list_expr) {
            const show_child_list_expr = field.foreign_key.show_child_list_expr.replace('{{', '').replace('}}', '')
            return eval(show_child_list_expr)
          } else {
            return true
          }
        }
        if (this.pageType === 'add') {
          return field.in_add === 1
        } else if (this.pageType === 'update') {
          return field.in_update === 1
        } else if (this.pageType === 'detail') {
          return field.in_detail === 1
        }
        return true
      },
      getValid() {
        let res = null
        let valid = 0;
        let showsNum = 0;
        if (Array.isArray(this.gridList) && this.gridList.length > 0) {
          this.gridList.forEach((item, index) => {
            if (Array.isArray(item.cols) && item.cols.length > 0) {
              item.cols.forEach((col, cIndex) => {
                let valids = this.$refs['fitem' + index][cIndex].getValid();
                console.log('字段校验', valids, col);
                showsNum++;
                if (valids.valid) {
                  valid++;
                } else {
                  debugger
                }
              })
            }
          })
        } else {
          this.allField.map((item, index) => {
            let valids = this.$refs.fitem[index].getValid();
            console.log('字段校验', valids, item);
            // if (item.display) {
            showsNum++;
            if (valids.valid) {
              valid++;
            } else {
              debugger
            }
          });
        }
        if (valid === showsNum) {
          return true
        } else {
          return false
        }
      },
      getFieldModel() {
        const isValid = this.getValid()
        let defaultValue = this.allField.reduce((res, cur) => {
          if (cur.defaultValue !== null && cur.defaultValue !== undefined) {
            res[cur.columns] = cur.defaultValue
          }
          return res
        }, {})
        if (isValid) {
          console.log('表单校验通过', this.fieldModel);
          let model = {};
          if (this.formType === 'add') {
            if (Array.isArray(this.gridList) && this.gridList.length > 0) {
              this.gridList.forEach((item, index) => {
                if (Array.isArray(item.cols) && item.cols.length > 0) {
                  item.cols.forEach((col, cIndex) => {
                    model[col.columns] = col.value
                  })
                }
              })
            } else {
              model = this.allField.reduce((res, cur) => {
                if (cur.value !== undefined) {
                  res[cur.columns] = cur.value
                }
                return res
              }, {})
            }

          } else if (this.formType === 'detail') {
            model = this.deepClone(this.fieldModel)
            if (Object.keys(model).length === 0) {
              if (Array.isArray(this.gridList) && this.gridList.length > 0) {
                this.gridList.forEach((item, index) => {
                  if (Array.isArray(item.cols) && item.cols.length > 0) {
                    item.cols.forEach((col, cIndex) => {
                      model[col.columns] = col.value
                    })
                  }
                })
              } else {
                model = this.allField.reduce((res, cur) => {
                  if (cur.value !== undefined) {
                    res[cur.columns] = cur.value
                  }
                  return res
                }, {})
              }
            }
          } else {
            switch (this.pageType) {
              case 'update':
                // for (let key in defaultValue) {
                //   model[key] = model[key] || defaultValue[key];
                // }
                for (let key in this.fieldModel) {
                  if (this.fieldModel[key] !== this.oldFieldModel[key]) {
                    model[key] = this.fieldModel[key];
                  }
                }
                if (Object.keys(model).length === 0) {
                  model = this.fieldMode
                  // uni.showToast({
                  //   title:'没有修改的数据',
                  //   icon:'none'
                  // })
                }
                break;
              case 'add':
                for (let key in this.fieldModel) {
                  if (this.fieldModel[key] === '' && key !== 'openid') {
                    delete this.fieldModel[key];
                  }
                }
                model = this.deepClone(this.fieldModel);
                break;
              case 'addchildlist':
                model = this.deepClone(this.fieldModel);
                break;
              case 'detaillist':
                for (let key in this.fieldModel) {
                  if (this.oldFieldModel[key] !== this.fieldModel[key]) {
                    model[key] = this.fieldModel[key];
                  }
                }
                break;
              default:
                for (let key in this.fieldModel) {
                  if (this.oldFieldModel[key] !== this.fieldModel[key]) {
                    model[key] = this.fieldModel[key];
                  }
                }
                break;
            }
          }
          if (Object.keys(model).length > 0) {
            if (Object.keys(this.childListData).length > 0) {
              model._child_list_data = []
              Object.keys(this.childListData).forEach(key => {
                let field = this.allField.find(item => item.constraint_name === key)
                if (field?.constraint_name) {
                  // if (this.showField(field) !== true) {
                  //   return
                  // }
                }
                model._child_list_data.push(...this.childListData[key])
              })
            }
            return model;
          } else {
            return false;
          }
        } else {
          console.log('表单校验失败', this.fieldModel);
          uni.showToast({
            title: '请检查输入数据是否完整有效',
            icon: 'none'
          });
          return false;
        }
      },
      setColData(e) {
        if (e && e.column) {
          this.handlerReduant(e)
          this.$emit('setColData', e)
        }
      },
      handlerReduant(obj, _dependFields) {
        // 处理冗余操作
        const e = this.deepClone(obj)
        for (let index = 0; index < this.allField.length; index++) {
          let item = this.allField[index]
          if (item?.redundant?.func && item.redundant.func.indexOf(e.column) > -1) {
            let data = this.deepClone(this.fieldModel)
            Object.keys(data).forEach(key => {
              if (Array.isArray(data[key])) {
                data[key] = data[key].toString()
              }
            })
            item.value = eval(`(${item.redundant.func})(data)`)
          }
          if (e.bx_col_type === 'fk' && e.column !== item.column && item.redundant && item?.redundant
            ?.dependField) {
            if (item.redundant.dependField === e.column && e.colData) {
              if (item.redundant.trigger === 'always') {
                if (e.colData && typeof e.colData === 'object' && Array.isArray(e
                    .colData) !==
                  true && Object.keys(e.colData).length > 0) {
                  item.old_value = item.value
                  item.value = e.colData[item.redundant.refedCol]
                  if (e.colData[item.redundant.refedCol] === 0) {
                    item.value = e.colData[item.redundant.refedCol]
                  }
                  let dependFields = this.allField.reduce((res, cur) => {
                    if (cur?.redundant?.dependField === item.column && cur.column !== item
                      .column) {
                      res.push(cur.column)
                    }
                    return res
                  }, [])

                } else {
                  // item.value = null
                }
                let dependFields = this.allField.reduce((res, cur) => {
                  if (cur?.redundant?.dependField === item.column && cur.column !== item
                    .column) {
                    res.push(cur.column)
                  }
                  return res
                }, [])
              } else if (item.redundant.trigger === 'isnull') {
                if (!item.value) {
                  if (e.colData && typeof e.colData === 'object' && Array.isArray(e
                      .colData) !==
                    true && Object.keys(e.colData).length > 0) {
                    item.old_value = item.value
                    item.value = e.colData[item.redundant.refedCol];
                  }
                }
              }
              this.fieldModel[item.column] = item.value;
            }
          }
        }
        return
      },
      setFieldModel(e) {
        console.log('setFieldModel', e.column, e.value)
        this.fieldModel[e.column] = e.value;
      },
      async onValChange(e) {
        // 保存已经发生变化的字段值
        e = this.deepClone(e)

        if (e.type === 'number' || e.type === 'digit') {
          e.value = e.value !== null && e.value !== undefined ? Number(e.value) : null;
        }
        this.fieldModel[e.column] = e.value;
        const fieldModel = this.fieldModel;
        const column = e.column

        let dependFields = this.allField.reduce((res, cur) => {
          if (cur?.redundant?.func && cur.redundant.func.indexOf(e.column) > -1) {
            res.push(cur.column)
          }
          // if (cur?.redundant?.dependField === e.column && cur.column !== e.column) {
          //   res.push(cur.column)
          // }
          return res
        }, [])
        if (dependFields && dependFields.length > 0) {
          await this.handlerReduant(e, dependFields)
        } else {}

        for (let index = 0; index < this.allField.length; index++) {
          let item = this.allField[index]
          if (item.column === e.column) {
            item = this.deepClone(e)
          }

          if (e?.moreConfig?.val_trigger) {
            let val_trigger = e?.moreConfig?.val_trigger;
            if (val_trigger.col === item.column || val_trigger.col.indexOf(item.column) !== -1) {
              let val = await this.getTriggerVal(val_trigger, this.fieldModel)
              if (val && val[item.column]) {
                item.value = val[item.column];
                this.fieldModel[item.column] = item.value;
              }
            }
          }

          if (item.display !== false) {
            item.display = true
          }
          if (item.column === e.column) {
            if (item.type === 'Set') {
              item.option_list_v2 = e.option_list_v2;
            }
          }

          if (!item.value && this.pageType === 'filter') {
            // item.value = '全部'
          }

          this.$set(this.allField, index, item)
          this.$nextTick(() => {
            if (item.type === 'Selector' && Array.isArray(item.option_list_v2?.conditions) && item
              .option_list_v2.conditions.find(cond => cond.colName === e.column)) {
              this.$refs.fitem[index].refresh()
            }
          })
        }
        this.$emit('value-blur', this.fieldModel, e);
      },
      onValBlur(e) {
        if (e.hasOwnProperty('value')) {
          console.log('onValBlur', e.column, e.value)
          this.fieldModel[e.column] = e.value;
        }
      },
      chooseLocation(e) {
        this.allField = this.allField.map((item, index) => {
          if (item.column === 'latitude' && e.latitude) {
            item.value = e.latitude;
          }
          if (item.column === 'longitude' && e.longitude) {
            item.value = e.longitude;
          }
          this.fieldModel[item.column] = item.value;
          this.$set(this.allField, index, item);
          return item;
        });
      },
      onReset() {
        let self = this
        if (Array.isArray(this.oldField) && this.oldField.length > 0) {
          this.allField = this.oldField.map((item, index) => {
            if (Array.isArray(item?.options) && item?.options.length > 0) {
              item.options = item?.options.map(item => {
                item.text = item.label;
                return item
              })
            }
            this.$refs.fitem[index].fieldData.value = item.value;
            this.fieldModel[item.columns] = item.value
            self.$refs.fitem[index]?.$refs?.optionSelector?.onreset?.()
            if (self.pageType === 'filter') {
              if (item.defaultValue) {
                item.value = item.defaultValue
              } else if (item.type === 'Selector') {
                item.value = ''
                if (self.fieldModel[item.columns]) {
                  self.fieldModel[item.columns] = ''
                }
                self.$refs.fitem[index].refresh()
              } else if (item.type === 'TreeSelector') {
                item.value = ''
                item.colData = null
                if (self.fieldModel[item.columns]) {
                  self.fieldModel[item.columns] = ''
                }
                self.$refs.fitem[index]?.reset?.()
              }
            }
            if (item.type === 'Set') {
              self.$refs.fitem[index].initSetOptions()
            }
            self.$set(self.allField, index, item);
            return item;
          });
          return true;
        } else {
          return false;
        }
      }
    },
    watch: {
      fields: {
        deep: true,
        immediate: true,
        handler(newValue, oldValue) {
          if (Array.isArray(newValue) && newValue.length > 0) {
            if (this.allField.length === 0) {
              this.oldField = this.deepClone(newValue);
            }
            this.allField = newValue
          }
        }
      },
      // 'fields.value': {
      //   handler(newValue, oldValue) {
      //     debugger
      //     this.fieldData.value = newValue
      //   }
      // },
      moreConfig: {
        handler(newValue, oldValue) {
          if (newValue) {
            this.more_config = this.deepClone(newValue);
          }
        }
      }
    }
  };
</script>

<style lang="scss">
  .a-form {
    padding: 0;
    width: 100%;
    // max-width: 128rem;
    margin: 0 auto;
    display: flex;
    flex-direction: column;

    .form-item-label {
      min-width: 12rem;
    }
  }

  .section-name {
    padding: 5px 10px 0;
    color: #B8BAC0;

    // line-height: 30px;
    &.show {
      padding: 10px 10px 5px;
      line-height: 30px;
    }
  }

  .field-item {
    // overflow: hidden; //不能hidden hidden的话 下拉选择就用不了了
    box-sizing: border-box;

    &.hidden {
      width: 0 !important;
      min-width: 0 !important;
      display: none;
    }

    // .before-section {
    //   border-bottom-left-radius: 20rpx;
    //   border-bottom-right-radius: 20rpx;
    //   // margin-bottom: 20rpx;
    // }

    // .section-top {
    //   border-top-left-radius: 20rpx;
    //   border-top-right-radius: 20rpx;
    // }

    // .section-top:first-child {
    //   margin-top: 0;
    // }
  }

  // @media screen and (min-width:450px) {
  //   .field-item {
  //     background-color: #fff;
  //     border: 1px solid #E5E6E9;
  //     // margin-right: 10px;
  //     // margin-left: 10px;
  //     margin-bottom: 10px;
  //     // border-radius: 8px;
  //   }
  // }

  // @media screen and (max-width:750px) {
  //   .field-item {
  //     flex: 1;
  //     min-width: 90%;
  //   }
  // }

  // @media screen and (min-width: 750px) {
  //   .a-form {}

  //   .field-item {
  //     // max-width: 30%;
  //     min-width: 300px;
  //     flex: 1;
  //     // min-width: 250px;
  //     background-color: #fff;
  //     border: 1px solid #E5E6E9;
  //     // margin-right: 10px;
  //     // margin-left: 10px;
  //     margin-bottom: 10px;
  //     // border-radius: 8px;
  //     // max-width: 300px;

  //     .form-item {}
  //   }
  // }

  .filter-model {
    .field-item {
      width: 50%;
      display: inline-flex;
      border: none;

      .form-item {
        width: 100%;

        ::v-deep .form-item-content input {
          height: 5rem;
          font-size: $retail-font-size-xs;
          padding: $retail-button-padding-base;
          border: 1px solid #E5E6E9;
        }
      }
    }

  }

  .grid {
    background-color: #fff;
    padding: 0;

    .sub-title {
      height: 6rem;
      display: flex;
      align-items: center;
      border-radius: 1rem;
      padding: 0 3rem;
      font-size: 2.4rem;
      background-color: $retail-color-primary-light;
      margin: 1rem 0;

      .subsection {
        display: flex;
        border: 1px solid $retail-color-primary;
        border-radius: 1rem;
        margin-left: 3rem;
        overflow: hidden;

        &-item {
          width: 8rem;
          height: 4rem;
          display: flex;
          align-items: center;
          justify-content: center;
          color: $retail-color-primary;

          &.active {
            background-color: $retail-color-primary;
            color: #fff;
          }
        }
      }
    }

    .grid-area {
      display: grid;
      width: 100%;
      border-radius: 1rem;
      margin: .5rem 0;
      padding: 0 1rem;

      .field-item {
        ::v-deep .form-item {
          height: 100%;

          .form-item-label {
            // font-weight: bold;
          }

          .form-item-content.label-top {
            width: 100%;
          }

          .form-item-content {
            justify-content: flex-start;
            height: 100%;

            .input-placeholder {
              text-align: left;
            }

            .form-item-content_value {
              justify-content: flex-start;
              width: 100%;

              &.checkbox-group {
                justify-content: space-between;
              }
            }

            .bx-checkbox {
              margin-right: 1rem;
            }
          }
        }
      }
    }
  }
</style>
